package com.example.framework509.common.services.Impl;

import com.example.framework509.common.entities.MapperParam;
import com.example.framework509.common.exceptions.JdbcException;
import com.example.framework509.common.exceptions.ParamFieldException;
import com.example.framework509.common.services.OneToOneMapperService;

import java.util.List;

public class OneToOneAutoMapperImpl<E,PRIMARY_CLASS,SECONDARY_CLASS> extends AutoMapperServiceImpl<E,PRIMARY_CLASS,SECONDARY_CLASS> implements OneToOneMapperService<E> {

    @Override
    protected void addMapperInRedis(MapperParam param) {
        redisUtil.set(ENTITY_NAME_LOWER + PRIMARY_FIELD_NAME + ":" + param.getPrimaryId(), param.getSecondaryId());
        redisUtil.set(ENTITY_NAME_LOWER + SECONDARY_FIELD_NAME + ":" + param.getSecondaryId(), param.getPrimaryId());
    }

    @Override
    protected void delMapperInRedis(MapperParam param) {
        redisUtil.del(ENTITY_NAME_LOWER + PRIMARY_FIELD_NAME + ":" + param.getPrimaryId());
        redisUtil.del(ENTITY_NAME_LOWER + SECONDARY_FIELD_NAME + ":" + param.getSecondaryId());
    }

    @Override
    protected boolean hasSameMapper(Integer primaryId, Integer secondaryId) {
        Object o = redisUtil.get(ENTITY_NAME_LOWER + PRIMARY_FIELD_NAME + ":" + primaryId);
        if ( o!=null && o.toString().equals(secondaryId.toString()))
            return true;
        Integer secondaryIdFromPrimaryId = getSecondaryIdFromPrimaryId(primaryId);
        Integer primaryIdFromSecondaryId = getPrimaryIdFromSecondaryId(secondaryId);
        if (secondaryIdFromPrimaryId != null || primaryIdFromSecondaryId !=null)
            throw new JdbcException("One to One relation not matched");
        return false;
    }

    @Override
    public Integer getSecondaryIdFromPrimaryId(Integer primaryId) {
        getAllEntityNum();
        Object resId = redisUtil.get(ENTITY_NAME_LOWER + PRIMARY_FIELD_NAME + ":" + primaryId);
        if (resId == null) {
            return null;
        }
        return Integer.parseInt((resId).toString());
    }

    @Override
    public Integer getPrimaryIdFromSecondaryId(Integer secondaryId) {
        getAllEntityNum();
        Object obj = redisUtil.get(ENTITY_NAME_LOWER+SECONDARY_FIELD_NAME+":"+secondaryId);
        if (obj == null) {
            return null;
        }
        return Integer.parseInt(obj.toString());
    }

    public PRIMARY_CLASS getPrimaryEntityFromSecondaryId(Integer secondaryId){
        Integer primaryIdFromSecondaryId = getPrimaryIdFromSecondaryId(secondaryId);
        PRIMARY_CLASS entityFromId = primaryEntityBaseService.getEntityFromId(primaryIdFromSecondaryId);
        return entityFromId;
    }

    public SECONDARY_CLASS getSecondaryEntityFromPrimaryId(Integer primaryId){
        Integer secondaryIdFromPrimaryId = getSecondaryIdFromPrimaryId(primaryId);
        SECONDARY_CLASS entityFromId = secondaryEntityBaseService.getEntityFromId(secondaryIdFromPrimaryId);
        return entityFromId;
    }

    @Override
    protected void editSecFetchCallBack(Integer primaryId,List<Integer> secondaryIds) throws Exception {
        if(secondaryIds.size()!=1) throw new ParamFieldException("映射关系数量异常");
        Integer secondaryIdFromPrimaryId = getSecondaryIdFromPrimaryId(primaryId);
        Integer primaryFromAdd = getPrimaryIdFromSecondaryId(secondaryIds.get(0));
        if(primaryFromAdd !=null) throw new ParamFieldException("添加映射关系有冲突");
        delMapper(new MapperParam(primaryId,secondaryIdFromPrimaryId));
        addMapper(new MapperParam(primaryId,secondaryIds.get(0)));
    }

    @Override
    protected void editPriFetchCallBack(Integer secondaryId,List<Integer> primaryIds) throws Exception {
        if(primaryIds.size()!=1) throw new ParamFieldException("映射关系数量异常");
        Integer primaryIdFromSecondaryId = getPrimaryIdFromSecondaryId(secondaryId);
        Integer secondaryIdAdd = getSecondaryIdFromPrimaryId(primaryIds.get(0));
        if(secondaryIdAdd !=null) throw new ParamFieldException("添加映射关系有冲突");
        delMapper(new MapperParam(primaryIdFromSecondaryId,secondaryId));
        addMapper(new MapperParam(primaryIds.get(0),secondaryId));
    }
}
